package zunge.lbe1;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

/**
 * Folds by user
 */
public class DataFold {
	
	public static final int V = 10; //10-fold cross validation
	public static final double testRatio = 0.3;// In test set, we know only {ratio} labels of the apps.
	
	public static List<DataFold> getDataFolds(Data dataInput, boolean create) throws IOException{
		List<DataFold> dataFolds = new ArrayList<DataFold>(V);
		for(int v = 0;v < V;++v){
			dataFolds.add(new DataFold(dataInput, v, create));
		}
		return dataFolds;
	}
	
	Data data;
	String folder;
	int v;
	
	public String getTrainSetFile(){return folder + "train.txt";} //format: uid aid pid did
	public String getTestSetFile(){return folder + "test.txt";} //format: uid aid pid did
	
	
	
	public DataFold(Data data, int v, boolean create) throws IOException{
		this.data = data;
		this.folder = data.folder + "fold_"+v+"/";
		this.v = v;
		
		if(create){
			new File(folder).mkdir();
			
			//read record_u file, generate train & test dataset
			BufferedReader bru = new BufferedReader(new FileReader(data.getRecordUFile()));
			BufferedWriter bwtrain = new BufferedWriter(new FileWriter(getTrainSetFile()));
			BufferedWriter bwtest = new BufferedWriter(new FileWriter(getTestSetFile()));
			
			int uid;
			String line;
			while((line=bru.readLine())!=null){
				String[] frags = line.split(" ");
				uid = Integer.parseInt(frags[0]);
				if(uid%V!=v){//Train
					for(int i = 1;i < frags.length;++i){
						String[] fields = frags[i].split(":");
						bwtrain.write(uid+" "+fields[0]+" "+fields[1]+" "+fields[2]+"\n");
					}
				}
				
				else{//Test
					//Random choose #ration apps as training hints (Make sure all users have at least 1 training app)
					HashSet<Integer> appSet = new HashSet<Integer>();
					for(int i = 1;i < frags.length;++i){
						String[] fields = frags[i].split(":");
						appSet.add(Integer.parseInt(fields[0]));
					}
					List<Integer> appList = new ArrayList<Integer>(appSet);
					Collections.shuffle(appList);
					int trainSize = Math.max(1, new Double(appList.size() * testRatio).intValue());
					appSet = new HashSet<Integer>(appList.subList(0, trainSize));
					
					for(int i = 1;i < frags.length;++i){
						String[] fields = frags[i].split(":");
						if(appSet.contains(Integer.parseInt(fields[0]))){//Train Hint
							bwtrain.write(uid+" "+fields[0]+" "+fields[1]+" "+fields[2]+"\n");
						}
						else{
							bwtest.write(uid+" "+fields[0]+" "+fields[1]+" "+fields[2]+"\n");
						}
					}
				}
			}
			
			bru.close();
			bwtrain.close();
			bwtest.close();
		}
		else{
		}
	}
	
}
